package cn.zyjblogs.starter.oauth.token;

import cn.zyjblogs.crypto.sm2.SM2KeyPair;
import cn.zyjblogs.starter.common.autoconfigure.rsa.RsaKeyProperties;
import cn.zyjblogs.starter.common.entity.constant.CommonRedisKeyConstant;
import cn.zyjblogs.starter.common.utils.string.StringUtils;
import cn.zyjblogs.starter.redis.utils.RedisTemplateHandler;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.io.IOUtils;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
import org.springframework.util.Assert;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Paths;

/**
 * @author zhuyijun
 */
@Log4j2
@Configuration
@RequiredArgsConstructor
public class TokenConfig {

    private final RsaKeyProperties rsaKeyProperties;
    private final OauthAccessTokenConverter oauthAccessTokenConverter;
    private final RedisTemplateHandler<String, String> redisTemplateHandler;

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    /**
     * 令牌存储策略
     *
     * @return
     */
    @Bean
    public TokenStore tokenStore() {
        //JWT令牌存储方案
        return new JwtTokenStore(accessTokenConverter());
    }

    @Bean("sm2KeyPair")
    public SM2KeyPair sm2KeyPair() {
        String publicKey = "";
        String privateKey = "";
        try {
            publicKey = redisTemplateHandler.get(CommonRedisKeyConstant.REDIS_KEY_PUBLIC_RSA);
            privateKey = redisTemplateHandler.get(CommonRedisKeyConstant.REDIS_KEY_PRIVATE_RSA);
        } catch (Exception e) {
            log.error("redis连接失败,无法获取数据");
        }
        if (StringUtils.isEmpty(publicKey) || StringUtils.isEmpty(privateKey)) {
            try {
                publicKey = IOUtils.toString(Paths.get(rsaKeyProperties.getPubKeyPath()).toUri(), StandardCharsets.UTF_8);
                privateKey = IOUtils.toString(Paths.get(rsaKeyProperties.getPriKeyPath()).toUri(), StandardCharsets.UTF_8);
            } catch (IOException e) {
                throw new RuntimeException(StringUtils.format("rsa秘钥读取失败，读取路径如下 公钥:{} 私钥:{}" + rsaKeyProperties.getPubKeyPath(), rsaKeyProperties.getPriKeyPath()));
            }
            return new SM2KeyPair(publicKey, privateKey);
        }
        return new SM2KeyPair(publicKey, privateKey);
    }

    @Bean
    public JwtAccessTokenConverter accessTokenConverter() {
        JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
        if (rsaKeyProperties.getEnable()) {
            SM2KeyPair rsaKey = sm2KeyPair();
            // 公钥验签
            converter.setVerifierKey(rsaKey.getPublicKey());
        }
        Assert.notNull(oauthAccessTokenConverter, "oauthAccessTokenConverter is required");
        converter.setAccessTokenConverter(oauthAccessTokenConverter);
        return converter;
    }
}
